﻿using Quartz;
using RuoVea.ExDto;
using RuoVea.ExEnum;
using RuoVea.ExIdGen;
using RuoVea.ExUtil;
using RuoVea.QuartzNetUI.Entitys;
using RuoVea.QuartzNetUI.Server.Dto;
using SqlSugar;
using System.Linq.Expressions;

namespace RuoVea.QuartzNetUI.Server.Impl
{
    /// <summary>
    /// 任务调度详情
    /// </summary>
    public class TaskDetailService : ITaskDetailService
    {
        private readonly ISqlSugarClient _sqlSugarClient;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlSugarClient"></param>
        public TaskDetailService(ISqlSugarClient sqlSugarClient)
        {
            _sqlSugarClient = sqlSugarClient;
        }
        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public async Task<bool> AnyAsync(Expression<Func<TaskDetail, bool>> expression)
        {
            return await _sqlSugarClient.Queryable<TaskDetail>().AnyAsync(expression);
        }
        /// <summary>
        /// 获取一个
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<RestfulResult<TaskDetail>> GetByIdAsync(long Id)
        {
            RestfulResult<TaskDetail> result = new RestfulResult<TaskDetail>() { Code = ExEnum.CodeStatus.OK };
            try
            {
                var data = await _sqlSugarClient.Queryable<TaskDetail>().Where(x => x.Id == Id && x.Deleted == IsDelete.N).FirstAsync();
                result.Data = data;
            }
            catch (Exception ex)
            {
                result.Code = CodeStatus.BadRequest;
                result.Message = ex.Message;
            }

            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public TaskDetail DtoToDetail(TaskDetailDto data)
        {
            return new TaskDetail
            {
                Id = data.Id,
                SchedName = data.SchedName,
                JobName = data.JobName,
                JobGroup = data.JobGroup,
                BeginTime = data.BeginTime,
                EndTime = data.EndTime,
                Cron = data.Cron,
                RunTimes = data.RunTimes,
                IntervalSecond = data.IntervalSecond,
                ScheduleType = data.ScheduleType ?? Enums.ScheduleTypeEnum.Http,
                TriggerType = data.TriggerType ?? Enums.TriggerTypeEnum.Simple,
                RunType = data.RunType ?? RequestTypeEnum.Get,
                //Interval = data.Interval,
                RequestUrl = data.RequestUrl,
                Headers = data.Headers,
                Parameters = data.Parameters,
                AssemblyName = data.AssemblyName,
                ClassName = data.ClassName,
                //JobClassName = data.JobClassName,
                Description = data.Description,
                MailMsgType = data.MailMsgType ?? Enums.SendMsgTypeEnum.None,
                SendMailers = data.SendMailers,
                HorkMsgType = data.HorkMsgType ?? Enums.SendMsgTypeEnum.None,
                HorkUrl = data.HorkUrl,
            };
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public TaskDetail InDtoToDetail(TaskDetailInDto data)
        {
            return new TaskDetail
            {
                Id = data.Id,
                SchedName = data.SchedName,
                JobName = data.JobName,
                JobGroup = data.JobGroup,
                BeginTime = data.BeginTime,
                EndTime = data.EndTime,
                Cron = data.Cron,
                RunTimes = data.RunTimes,
                IntervalSecond = data.IntervalSecond,
                ScheduleType = data.ScheduleType ?? Enums.ScheduleTypeEnum.Http,
                TriggerType = data.TriggerType ?? Enums.TriggerTypeEnum.Simple,
                RunType = data.RunType ?? RequestTypeEnum.Get,
                //Interval = data.Interval,
                RequestUrl = data.RequestUrl,
                Headers = data.Headers,
                Parameters = data.Parameters,
                AssemblyName = data.AssemblyName,
                ClassName = data.ClassName,
                //JobClassName = data.JobClassName,
                Description = data.Description,
                MailMsgType = data.MailMsgType ?? Enums.SendMsgTypeEnum.None,
                SendMailers = data.SendMailers,

                HorkMsgType = data.HorkMsgType ?? Enums.SendMsgTypeEnum.None,
                HorkUrl = data.HorkUrl,
            };
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public TaskDetailDto DetailToDto(TaskDetail data)
        {
            return new TaskDetailDto
            {
                Id = data.Id,
                SchedName = data.SchedName,
                JobName = data.JobName,
                JobGroup = data.JobGroup,
                BeginTime = data.BeginTime,
                EndTime = data.EndTime,
                Cron = data.Cron,
                RunTimes = data.RunTimes,
                IntervalSecond = data.IntervalSecond,
                ScheduleType = data.ScheduleType,
                TriggerType = data.TriggerType,
                RunType = data.RunType,
                //Interval = data.Interval,
                RequestUrl = data.RequestUrl,
                Headers = data.Headers,
                Parameters = data.Parameters,
                AssemblyName = data.AssemblyName,
                ClassName = data.ClassName,
                //JobClassName = data.JobClassName,
                Description = data.Description,
                MailMsgType = data.MailMsgType,
                SendMailers = data.SendMailers,
                HorkMsgType = data.HorkMsgType,
                HorkUrl = data.HorkUrl,

                CreateTime = data.CreateTime,
                Status = data.Status,

            };
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public TaskDetailInDto DetailToInDto(TaskDetail data)
        {

            return new TaskDetailInDto
            {
                Id = data.Id,
                SchedName = data.SchedName,
                JobName = data.JobName,
                JobGroup = data.JobGroup,
                BeginTime = data.BeginTime,
                EndTime = data.EndTime,
                Cron = data.Cron,
                RunTimes = data.RunTimes,
                IntervalSecond = data.IntervalSecond,
                ScheduleType = data.ScheduleType,
                TriggerType = data.TriggerType,
                RunType = data.RunType,
                //Interval = data.Interval,
                RequestUrl = data.RequestUrl,
                Headers = data.Headers,
                Parameters = data.Parameters,
                AssemblyName = data.AssemblyName,
                ClassName = data.ClassName,
                //JobClassName = data.JobClassName,
                Description = data.Description,
                MailMsgType = data.MailMsgType,
                SendMailers = data.SendMailers,
            };
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<RestfulResult<IList<TaskDetailDto>>> GetTaskDetailListAsync(TaskDetailQueryDto data)
        {
            RestfulResult<IList<TaskDetailDto>> result = new RestfulResult<IList<TaskDetailDto>>() { Code = ExEnum.CodeStatus.OK };
            try
            {
                var rows = await _sqlSugarClient.Queryable<TaskDetail>().Where(x => x.Deleted == ExEnum.IsDelete.N)
                     .WhereIF(data.Status != null, x => x.Status == data.Status)
                     .WhereIF(data.JobGroup.NotNullOrWhiteSpace(), x => x.JobGroup.Contains(data.JobGroup))
                     .WhereIF(data.JobName.NotNullOrWhiteSpace(), x => x.JobName.Contains(data.JobName))
                     .OrderByDescending(x => x.CreateTime)
                     .ToListAsync();

                List<TaskDetailDto> details = new List<TaskDetailDto>();
                foreach (var item in rows)
                    details.Add(DetailToDto(item));
                result.Data = details;
            }
            catch (Exception ex)
            {
                result.Code = ExEnum.CodeStatus.BadRequest;
                result.Message = ex.Message;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<RestfulResult<PageResult<TaskDetailDto>>> GetTaskDetailPageListAsync(TaskDetailPageDto data)
        {
            RestfulResult<PageResult<TaskDetailDto>> result = new RestfulResult<PageResult<TaskDetailDto>>
            {
                Code = ExEnum.CodeStatus.OK,
                Data = new PageResult<TaskDetailDto>(data.PageNo, data.PageSize)
            };
            try
            {
                RefAsync<int> totalNumber = 0;
                var rows = await _sqlSugarClient.Queryable<TaskDetail>().Where(x => x.Deleted == ExEnum.IsDelete.N)
                    .WhereIF(data.Filter != null && data.Filter.Status != null, x => x.Status == data.Filter.Status)
                    .WhereIF(data.Filter != null && data.Filter.JobGroup.NotNullOrWhiteSpace(), x => x.JobGroup.Contains(data.Filter.JobGroup))
                    .WhereIF(data.Filter != null && data.Filter.JobName.NotNullOrWhiteSpace(), x => x.JobName.Contains(data.Filter.JobName))
                    //.OrderByIF(data.Sidx.IsNullOrWhiteSpace(), $"{data.Sidx ?? "Create_Time" + " " + data.Sord ?? "desc"}")
                    .OrderByDescending(x => x.CreateTime)
                    .ToPageListAsync(data.PageNo, data.PageSize, totalNumber);
                result.Data.TotalRows = totalNumber.Value;
                List<TaskDetailDto> details = new List<TaskDetailDto>();
                foreach (var item in rows)
                {
                    details.Add(DetailToDto(item));
                }
                result.Data.Rows = details;

            }
            catch (Exception ex)
            {
                result.Code = CodeStatus.BadRequest;
                result.Message = ex.Message;
            }

            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<RestfulResult> InsertAsync(TaskDetail data)
        {
            RestfulResult result = new RestfulResult { Code = CodeStatus.OK };
            try
            {
                if (data.JobName.IsNullOrWhiteSpace())
                    throw new ArgumentException($"{nameof(data.JobName)} 数据不能为空.");
                if (data.JobGroup.IsNullOrWhiteSpace())
                    throw new ArgumentException($"{nameof(data.JobGroup)} 数据不能为空.");
                data.Status = StatusEnum.DISABLE;
                if (data.TriggerType == Enums.TriggerTypeEnum.Corn)
                {
                    if (data.Cron.IsNullOrWhiteSpace())
                        throw new ArgumentException($"{nameof(data.Cron)} 数据不能为空.");

                    if (!CronExpression.IsValidExpression(data.Cron))
                        throw new ArgumentException("Cron表达式错误.");

                }

                //if (data.RequestUrl.NotNullOrWhiteSpace() && data.RunType != ExEnum.RequestTypeEnum.Run)
                //{
                //    data.AssemblyName = "RuoVea.QuartzNetUI";
                //    data.ClassName = "RuoVea.QuartzNetUI.Job.HttpJob";
                //}
                data.CreateTime = DateTime.Now;
                data.Deleted = IsDelete.N;
                var resultData = await _sqlSugarClient
                    .Insertable<TaskDetail>(data)
                    .IgnoreColumns(true)
                    .ExecuteCommandAsync();
                if (resultData > 0)
                {
                    result.Message = "提交成功.";
                    return result;
                }
                else
                {
                    result.Code = ExEnum.CodeStatus.BadRequest;
                    result.Message = "提交失败.";
                }
            }
            catch (ArgumentException ex)
            {
                result.Code = ExEnum.CodeStatus.BadRequest;
                result.Message = ex.Message;
            }
            catch (Exception ex)
            {
                result.Code = ExEnum.CodeStatus.BadRequest;
                result.Message = ex.Message;
            }
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<RestfulResult> UpdateAsync(TaskDetail data)
        {
            RestfulResult result = new RestfulResult { Code = ExEnum.CodeStatus.OK };
            try
            {
                int resultData = await _sqlSugarClient
                                            .Updateable<TaskDetail>(data)
                                            .IgnoreColumns(true)
                                            .ExecuteCommandAsync();
                if (resultData > 0)
                {
                    result.Message = "更新成功.";
                    return result;
                }
                else
                {
                    result.Code = ExEnum.CodeStatus.BadRequest;
                    result.Message = "更新提交失败.";
                }
            }
            catch (Exception ex)
            {
                result.Code = ExEnum.CodeStatus.BadRequest;
                result.Message = ex.Message;
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<RestfulResult> DeleteAsync(TaskDetaiDeleteDto data)
        {
            RestfulResult result = new RestfulResult { Code = ExEnum.CodeStatus.OK };
            try
            {
                result.Data = await _sqlSugarClient.Deleteable<TaskDetail>(new TaskDetail { Id = data.Id }).ExecuteCommandAsync();
            }
            catch (Exception ex)
            {
                result.Code = ExEnum.CodeStatus.BadRequest;
                result.Message = ex.Message;
            }
            return result;
        }

        /// <summary>
        /// 保存设置
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<RestfulResult> SaveSetting(TaskSettingDto data)
        {
            RestfulResult result = new RestfulResult { Code = ExEnum.CodeStatus.OK };
            try
            {
                if (data == null) { result.Message = "无关键信息."; result.Code = CodeStatus.BadRequest; return result; }

                if (data.Code.IsNullOrWhiteSpace()) { result.Message = "代码不能为空."; result.Code = CodeStatus.BadRequest; return result; }

                bool hasData = await _sqlSugarClient.Queryable<TaskSetting>().WhereIF(data.Id > 0, x => x.Id != data.Id).AnyAsync(x => x.Code == data.Code);
                if(hasData) { result.Message = "代码不能重复."; result.Code = CodeStatus.BadRequest; return result; }
                if (data.Id <= 0) { data.Id = IdGenerator.Id; }
                var saveData = new TaskSetting
                {
                    Id = data.Id,
                    Code = data.Code,
                    EmailAccount = data.EmailAccount,
                    EmaillPass = data.EmaillPass,
                };

                var storag = _sqlSugarClient.Storageable(saveData).ToStorage();
                int resultInser = await storag.AsInsertable.ExecuteCommandAsync();//不存在插入
                int resultUpdate = await storag.AsUpdateable.ExecuteCommandAsync();//存在更新
                if ((resultInser + resultUpdate) < 0)
                {
                    result.Message = "保存设置失败.";
                    result.Code = CodeStatus.BadRequest;
                }
                result.Message = "保存设置成功.";
            }
            catch (Exception ex)
            {
                result.Code = ExEnum.CodeStatus.BadRequest;
                result.Message = ex.Message;
            }
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<RestfulResult> GetSettingByCode(string data)
        {
            RestfulResult result = new RestfulResult { Code = ExEnum.CodeStatus.OK };
            try
            {
                if (data.IsNullOrWhiteSpace()) { result.Message = "无关键信息."; result.Code = CodeStatus.BadRequest; return result; }
                var resultData = await _sqlSugarClient.Queryable<TaskSetting>().Where(x => x.Code == data).FirstAsync();
                if (resultData == null)
                {
                    result.Message = "无相关信息."; result.Code = CodeStatus.NoContent; return result;
                }
                result.Data = resultData;
            }
            catch (Exception ex)
            {
                result.Code = ExEnum.CodeStatus.BadRequest;
                result.Message = ex.Message;
            }
            return result;
        }

    }
}
